package breakthrough;

public class BoardEvaluator
{
	private static final int WIN_GAME_VALUE = 500000;//100000;
	private static final int PAWN_VALUE = 1500;
	private static final int PAWN_ROW_MULTIPLIER = 20;
	private static final int HCONNECTION_VALUE = 250;//50;
	private static final int VCONNECTION_VALUE = 15;//20;
	private static final int PAWN_ATTACK_VALUE = 1500;//100;
	private static final int PAWN_CAPTURE_RISK_VALUE = 1500;//100;
	private static final int PAWN_PROTECTION_VALUE = 100;//150;
	private static final int COLUMN_HOLE_VALUE = 1000;//25;
	private static final int PAWN_MOBILITY_VALUE = 20;
	private static final int HOME_LEVEL_VALUE = 1200;//10;
	private static final int PAWN_ALMOST_WIN_VALUE_6 = 20000;
	private static final int PAWN_ALMOST_WIN_VALUE_5 = 10000;
	private static final int PAWN_MUST_GO_AHEAD_VALUE = 2000;
	private static final int PAWN_IN_WINNING_STATE_VALUE = 5500;
	
	/**
	 * Evaluates the board by combining pawn value of both players.
	 * @param aBoard
	 * @param aPlayer
	 * @return
	 */
	public static Board evaluateBoard(Board aBoard, Player aPlayer, Player maxPlayer)
	{
		int boardValue = 0;
		
		// Winning state
		if (aBoard.hasGameOverState() && aBoard.whiteWins())
		{
			//if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
				boardValue += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -WIN_GAME_VALUE : WIN_GAME_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.hasGameOverState() && aBoard.blueWins())
		{
			//if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
				boardValue += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -WIN_GAME_VALUE : WIN_GAME_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
		}
		
		// Column hole
		int whiteCount;
		int blueCount;
		
		for (int col = 0; col < Board.BOARD_HEIGTH; col++)
		{
			whiteCount = 0;
			blueCount = 0;
			for (int row = 0; row < Board.BOARD_WIDTH; row++)
			{
				if (aBoard.getBoardTable()[row][col] == 'w')
					whiteCount++;
				if (aBoard.getBoardTable()[row][col] == 'b')
					blueCount++;
			}
			
			if (whiteCount == 0)
			{
				//if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
					//boardValue += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -COLUMN_HOLE_VALUE : COLUMN_HOLE_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				boardValue += assignValue((maxPlayer.getPlayerValue() == aPlayer.getPlayerValue()) ? -COLUMN_HOLE_VALUE : COLUMN_HOLE_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			}
			if (blueCount == 0)
			{
				//if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
					//boardValue += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -COLUMN_HOLE_VALUE : COLUMN_HOLE_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				boardValue += assignValue((maxPlayer.getPlayerValue() == aPlayer.getPlayerValue()) ? -COLUMN_HOLE_VALUE : COLUMN_HOLE_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			}
			
			
			/*if (whiteCount == 0)
			{
				if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
					boardValue += COLUMN_HOLE_VALUE;
				else
					boardValue -= COLUMN_HOLE_VALUE;
			}
			if (blueCount == 0)
			{
				if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
					boardValue += COLUMN_HOLE_VALUE;
				else
					boardValue -= COLUMN_HOLE_VALUE;
			}*/
		}
		
		// Evaluate all pawns on the board sequentially
		int pawnValue = 0;
		for (int row = 0; row < Board.BOARD_WIDTH; row++)
		{
			for (int col = 0; col < Board.BOARD_HEIGTH; col++)
			{
				if (aBoard.getBoardTable()[row][col] != Board.NULL_PAWN)
				{
					pawnValue = evaluatePawn(aBoard, row, col, aPlayer, maxPlayer);
					//System.out.println("Player: " + aPlayer.getPlayerValue() + " - row: " + row + " - col: " + col + " - pawnValue: " + pawnValue);
					boardValue += pawnValue;
				}
			}
		}
		
		//System.out.println("BoardValue eval = " + boardValue);
		aBoard.setBoardValue(boardValue);
		
		return aBoard;
	}
	
	/**
	 * Evaluates a single pawn on the board regarding several criteria
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawn(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int pawnValue = PAWN_VALUE;
		
		// Evaluate pawn following each criteria
		pawnValue += evaluatePawnRowLevel(aBoard, row, col, aPlayer, maxPlayer);
		pawnValue += evaluatePawnOnHomeLevel(aBoard, row, col, aPlayer, maxPlayer);
		pawnValue += evaluatePawnAlmostWin6(aBoard, row, col, aPlayer, maxPlayer);
		pawnValue += evaluatePawnAlmostWin5(aBoard, row, col, aPlayer, maxPlayer);
		pawnValue += evaluatePawnCaptureRisk(aBoard, row, col, aPlayer, maxPlayer);
		pawnValue += evaluatePawnAttack(aBoard, row, col, aPlayer, maxPlayer);
		//pawnValue += evaluatePawnMustGoAhead(aBoard, row, col, aPlayer, maxPlayer);
		/*pawnValue += evaluatePawnProtection(aBoard, row, col, aPlayer);
		pawnValue += evaluatePawnMobility(aBoard, row, col, aPlayer);
		pawnValue += evaluatePawnHConnection(aBoard, row, col, aPlayer);
		pawnValue += evaluatePawnVConnection(aBoard, row, col, aPlayer);
		*/
		
		// Evaluate winning position
		if (isWinningPosition_3(aBoard, aPlayer) && !inThreat(aBoard, aPlayer))
		{
			// Remettre - si pas OK
			// Test avec maxPlayer
			//pawnValue += assignValue(PAWN_IN_WINNING_STATE_VALUE, Player.getColorFromPawn(aBoard.getBoardTable()[row][col]), aPlayer.getPlayerValue());
			pawnValue += assignValue((maxPlayer.getPlayerValue() == aPlayer.getPlayerValue()) ? -PAWN_IN_WINNING_STATE_VALUE : PAWN_IN_WINNING_STATE_VALUE, Player.getColorFromPawn(aBoard.getBoardTable()[row][col]), aPlayer.getPlayerValue());
			
			//System.out.println("Color = " + aPlayer.getPlayerValue());
		}
		
		// The pawn value will be negative if the pawn doesn't belong to the player
		if (Player.getColorFromPawn(aBoard.getBoardTable()[row][col]) != aPlayer.getPlayerValue())
			pawnValue = -pawnValue;
		
		return pawnValue;
	}
	
	public static boolean inThreat(Board aBoard, Player aPlayer)
	{
		if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			for (int row = Player.WHITE_HOME_LEVEL_ROW + 1; row >= Player.WHITE_HOME_LEVEL_ROW; row--)
			{
				for (int col = 0; col < Board.BOARD_HEIGTH; col++)
				if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
					return true;
			}
		}
		else
		{
			for (int row = Player.BLUE_HOME_LEVEL_ROW - 1; row <= Player.BLUE_HOME_LEVEL_ROW; row++)
			{
				for (int col = 0; col < Board.BOARD_HEIGTH; col++)
				if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
					return true;
			}
		}
		return false;
	}
	
	public static int evaluatePawnMustGoAhead(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		boolean columnClear = true;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			for (int i = row; i < Board.BOARD_HEIGTH && columnClear == true; i++)
			{
				if (aBoard.getBoardTable()[i][col] != Board.NULL_PAWN)
					columnClear = false;
			}
			
			// If not efficient, check capture risk also
			if (columnClear)
				//value += assignValue(PAWN_MUST_GO_AHEAD_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_MUST_GO_AHEAD_VALUE : PAWN_MUST_GO_AHEAD_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			for (int i = row; i >= 0 && columnClear == true; i--)
			{
				if (aBoard.getBoardTable()[i][col] != Board.NULL_PAWN)
					columnClear = false;
			}
			
			// If not efficient, check capture risk also
			if (columnClear)
				//value += assignValue(PAWN_MUST_GO_AHEAD_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_MUST_GO_AHEAD_VALUE : PAWN_MUST_GO_AHEAD_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				
		}	
		
		return value;
	}
	
	/**
	 * Pawn is only one row away from winning the game
	 * @param aBoard
	 * @param row
	 * @param col
	 * @return
	 */
	public static int evaluatePawnAlmostWin6(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		boolean canBeCaptured = false;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN && row == Player.BLUE_HOME_LEVEL_ROW)
		{
			if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
			{
				// Left diagonal
				if (row < 7 && col > 0 && aBoard.getBoardTable()[row + 1][col - 1] == Board.BLUE_PAWN)
					canBeCaptured = true;
				
				// Right diagonal
				if (row < 7 && col < 7 && aBoard.getBoardTable()[row + 1][col + 1] == Board.BLUE_PAWN)
					canBeCaptured = true;
			}
			if (!canBeCaptured)
				value = assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ALMOST_WIN_VALUE_6 : PAWN_ALMOST_WIN_VALUE_6, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN && row == Player.WHITE_HOME_LEVEL_ROW)
		{
			if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
			{
				// Left diagonal
				if (row > 0 && col > 0 && aBoard.getBoardTable()[row - 1][col - 1] == Board.WHITE_PAWN)
					canBeCaptured = true;
				// Right diagonal
				if (row > 0 && col < 7 && aBoard.getBoardTable()[row - 1][col + 1] == Board.WHITE_PAWN)
					canBeCaptured = true;
			}
			if (!canBeCaptured)
				value = assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ALMOST_WIN_VALUE_6 : PAWN_ALMOST_WIN_VALUE_6, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
		}
		
		return value;
	}
	
	/**
	 * Pawn is only two rows away from goal
	 * @param aBoard
	 * @param row
	 * @param col
	 * @return
	 */
	public static int evaluatePawnAlmostWin5(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		boolean canBeCaptured = false;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN && row == Player.BLUE_HOME_LEVEL_ROW - 1)
		{
			if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
			{
				// Left diagonal
				if (row < 7 && col > 0 && aBoard.getBoardTable()[row + 1][col - 1] == Board.BLUE_PAWN)
					canBeCaptured = true;
				
				// Right diagonal
				if (row < 7 && col < 7 && aBoard.getBoardTable()[row + 1][col + 1] == Board.BLUE_PAWN)
					canBeCaptured = true;
			}
			if (!canBeCaptured)
				value = assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ALMOST_WIN_VALUE_5 : PAWN_ALMOST_WIN_VALUE_5, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN && row == Player.WHITE_HOME_LEVEL_ROW + 1)
		{
			if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
			{
				// Left diagonal
				if (row > 0 && col > 0 && aBoard.getBoardTable()[row - 1][col - 1] == Board.WHITE_PAWN)
					canBeCaptured = true;
				// Right diagonal
				if (row > 0 && col < 7 && aBoard.getBoardTable()[row - 1][col + 1] == Board.WHITE_PAWN)
					canBeCaptured = true;
			}
			if (!canBeCaptured)
				value = assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ALMOST_WIN_VALUE_5 : PAWN_ALMOST_WIN_VALUE_5, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
		}
		
		return value;
	}
	
	// Evaluate: can be captured if I capture (avoid) -value...
	// Evaluate : killable avoid zigzag, dont move if opponent is on two level diagonal: because if i kill i will be killed too...
	// Think about aligning three on fifth row (good state for winning)...
	
	/**
	 * Evaluates the pawn row level
	 * @param aBoard
	 * @param row
	 * @param col
	 * @return
	 */
	public static int evaluatePawnRowLevel(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			if (row > Player.WHITE_HOME_LEVEL_ROW)
			{
				//if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
					value += assignValue((Math.abs(row - Player.WHITE_HOME_LEVEL_ROW) * PAWN_ROW_MULTIPLIER), Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				/*else
					value += assignValue(Math.abs(row - Player.WHITE_HOME_LEVEL_ROW) * PAWN_ROW_MULTIPLIER, Player.WHITE_PLAYER, aPlayer.getPlayerValue());*/
			}
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
		{
			if (row < Player.BLUE_HOME_LEVEL_ROW)
			{
				//if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
					value += assignValue((Math.abs(row - Player.WHITE_HOME_LEVEL_ROW) * PAWN_ROW_MULTIPLIER), Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				/*else
					value += assignValue(Math.abs(row - Player.WHITE_HOME_LEVEL_ROW) * PAWN_ROW_MULTIPLIER, Player.BLUE_PLAYER, aPlayer.getPlayerValue());*/
			}
		}
		return value;
	}
	
	/**
	 * Evaluates the pawn on home level: last line of defense
	 * @param aBoard
	 * @param row
	 * @param col
	 * @return
	 */
	public static int evaluatePawnOnHomeLevel(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			if (row < Player.WHITE_HOME_LEVEL_ROW)
				//value -= HOME_LEVEL_VALUE;
				value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -HOME_LEVEL_VALUE : HOME_LEVEL_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
		{
			if (row > Player.BLUE_HOME_LEVEL_ROW)
				//value -= HOME_LEVEL_VALUE;
				value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -HOME_LEVEL_VALUE : HOME_LEVEL_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		
		return value;
	}
	
	/**
	 * Evaluates pawn protection state: pawns on the lower diagonals are of the same color
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawnProtection(Board aBoard, int row, int col, Player aPlayer)
	{
		int value = 0;
		
		if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			// Left diagonal
			if (row > 0 && col > 0 && aBoard.getBoardTable()[row - 1][col - 1] != Board.NULL_PAWN && aBoard.getBoardTable()[row][col] != aBoard.getBoardTable()[row - 1][col - 1])
				value += PAWN_PROTECTION_VALUE;
			// Right diagonal
			if (row > 0 && col < 7 && aBoard.getBoardTable()[row - 1][col + 1] != Board.NULL_PAWN && aBoard.getBoardTable()[row][col] != aBoard.getBoardTable()[row - 1][col + 1])
				value += PAWN_PROTECTION_VALUE;
		}
		else if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			// Left diagonal
			if (row < 7 && col > 0 && aBoard.getBoardTable()[row + 1][col - 1] != Board.NULL_PAWN && aBoard.getBoardTable()[row][col] != aBoard.getBoardTable()[row + 1][col - 1])
				value += PAWN_PROTECTION_VALUE;
			// Right diagonal
			if (row < 7 && col < 7 && aBoard.getBoardTable()[row + 1][col + 1] != Board.NULL_PAWN && aBoard.getBoardTable()[row][col] != aBoard.getBoardTable()[row + 1][col + 1])
				value += PAWN_PROTECTION_VALUE;
		}
		
		return value;
	}
	
	/**
	 * Evaluates the pawn attack risks: can be captured by pawns on the diagonals
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawnAttack(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		//if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			// Adversary's pawn is two row in front, on the same column
			// It can be captured if it moves in the diagonals
			if (row < 6 && aBoard.getBoardTable()[row + 2][col] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pawn will be captured if it moves in front
			if (row < 6 && col > 0 && aBoard.getBoardTable()[row + 2][col - 1] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pawn will be captured if it moves in front
			if (row < 6 && col < 7 && aBoard.getBoardTable()[row + 2][col + 1] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pan will be captured if it moves in the left diagonal
			if (row < 6 && col > 1 && aBoard.getBoardTable()[row + 2][col - 2] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pan will be captured if it moves in the right diagonal
			if (row < 6 && col < 6 && aBoard.getBoardTable()[row + 2][col + 2] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.WHITE_PLAYER, aPlayer.getPlayerValue());
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
		//else if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			// Adversary's pawn is two row in front, on the same column
			// It can be captured if it moves in the diagonals
			if (row > 1 && aBoard.getBoardTable()[row - 2][col] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pawn will be captured if it moves in front
			if (row > 1 && col > 0 && aBoard.getBoardTable()[row - 2][col - 1] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pawn will be captured if it moves in front
			if (row > 1 && col < 7 && aBoard.getBoardTable()[row - 2][col + 1] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pan will be captured if it moves in the left diagonal
			if (row > 1 && col > 1 && aBoard.getBoardTable()[row - 2][col - 2] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			
			// Adversary's pan will be captured if it moves in the right diagonal
			if (row > 1 && col < 6 && aBoard.getBoardTable()[row - 2][col + 2] == Board.BLUE_PAWN)
				//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -PAWN_ATTACK_VALUE : PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				value += assignValue(PAWN_ATTACK_VALUE, Player.BLUE_PLAYER, aPlayer.getPlayerValue());
		}
		
		return value;
	}
	
	public static boolean canBeCapturedIfNoMove(Board aBoard, int row, int col)
	{
		/*if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			if (aBoard.getPreviousBoardTable()[row][col] != Board.NULL_PAWN && aBoard.getPreviousBoardTable()[row][col] == Board.BLUE_PAWN)
				return true;
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
		{
			if (aBoard.getPreviousBoardTable()[row][col] != Board.NULL_PAWN && aBoard.getPreviousBoardTable()[row][col] == Board.WHITE_PAWN)
				return true;
		}*/
		return false;
	}
	
	public static int evaluatePawnCaptureRisk(Board aBoard, int row, int col, Player aPlayer, Player maxPlayer)
	{
		int value = 0;
		
		if (aBoard.getBoardTable()[row][col] == Board.WHITE_PAWN)
		{
			if (canBeCapturedIfNoMove(aBoard, row, col))
			{
				/*System.out.println("White canBeCaught: row=" + row + "; col=" + col);
				value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.WHITE_PLAYER, aPlayer.getPlayerValue());*/
			}
			else
			{
				// Left diagonal
				if (row < 7 && col > 0 && aBoard.getBoardTable()[row + 1][col - 1] == Board.BLUE_PAWN)
					//value -= PAWN_CAPTURE_RISK_VALUE;
					value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.WHITE_PLAYER, aPlayer.getPlayerValue());
					//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -(PAWN_CAPTURE_RISK_VALUE + 1500) : (PAWN_CAPTURE_RISK_VALUE + 1500), Player.WHITE_PLAYER, aPlayer.getPlayerValue());
				// Right diagonal
				if (row < 7 && col < 7 && aBoard.getBoardTable()[row + 1][col + 1] == Board.BLUE_PAWN)
					//value -= PAWN_CAPTURE_RISK_VALUE;
					value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.WHITE_PLAYER, aPlayer.getPlayerValue());
					//value += assignValue((maxPlayer.getPlayerValue() == Player.WHITE_PLAYER) ? -(PAWN_CAPTURE_RISK_VALUE + 1500) : (PAWN_CAPTURE_RISK_VALUE + 1500), Player.WHITE_PLAYER, aPlayer.getPlayerValue());
			}
		}
		else if (aBoard.getBoardTable()[row][col] == Board.BLUE_PAWN)
		{
			if (canBeCapturedIfNoMove(aBoard, row, col))
			{
				/*System.out.println("Blue canBeCaught: row=" + row + "; col=" + col);
				value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.BLUE_PLAYER, aPlayer.getPlayerValue());*/
			}
			else
			{
				// Left diagonal
				if (row > 0 && col > 0 && aBoard.getBoardTable()[row - 1][col - 1] == Board.WHITE_PAWN)
					//value += PAWN_CAPTURE_RISK_VALUE;
					value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.BLUE_PLAYER, aPlayer.getPlayerValue());
					//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -(PAWN_CAPTURE_RISK_VALUE + 1500) : (PAWN_CAPTURE_RISK_VALUE + 1500), Player.BLUE_PLAYER, aPlayer.getPlayerValue());
				// Right diagonal
				if (row > 0 && col < 7 && aBoard.getBoardTable()[row - 1][col + 1] == Board.WHITE_PAWN)
					//value += PAWN_CAPTURE_RISK_VALUE;
					value += assignValue((PAWN_CAPTURE_RISK_VALUE + 1500), Player.BLUE_PLAYER, aPlayer.getPlayerValue());
					//value += assignValue((maxPlayer.getPlayerValue() == Player.BLUE_PLAYER) ? -(PAWN_CAPTURE_RISK_VALUE + 1500) : (PAWN_CAPTURE_RISK_VALUE + 1500), Player.BLUE_PLAYER, aPlayer.getPlayerValue());
			}
		}
		
		return value;
	}
	
	/**
	 * Evaluates pawn move possibilities
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawnMobility(Board aBoard, int row, int col, Player aPlayer)
	{
		int value = 0;
		
		if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			// Move ahead.
			if (row + 1 < Board.BOARD_WIDTH && aBoard.getBoardTable()[row + 1][col] == Board.NULL_PAWN)
				value += PAWN_MOBILITY_VALUE;

			// Left diagonal move.
			if (row + 1 < Board.BOARD_WIDTH && col - 1 >= 0 && aBoard.getBoardTable()[row + 1][col - 1] != Board.WHITE_PAWN)
				value += PAWN_MOBILITY_VALUE;
			
			// Right diagonal move.
			if (row + 1 < Board.BOARD_WIDTH && col + 1 < Board.BOARD_HEIGTH && aBoard.getBoardTable()[row + 1][col + 1] != Board.WHITE_PAWN)
				value += PAWN_MOBILITY_VALUE;
		}
		else if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			// Move ahead.
			if (row > 0 && aBoard.getBoardTable()[row - 1][col] == Board.NULL_PAWN)
				value += PAWN_MOBILITY_VALUE;

			// Left diagonal move.
			if (row > 0 && col - 1 >= 0 && aBoard.getBoardTable()[row - 1][col - 1] != Board.BLUE_PAWN)
				value += PAWN_MOBILITY_VALUE;
			
			// Right diagonal move.
			if (row > 0 && col + 1 < Board.BOARD_HEIGTH && aBoard.getBoardTable()[row - 1][col + 1] != Board.BLUE_PAWN)
				value += PAWN_MOBILITY_VALUE;
		}
		
		return value;
	}
	
	/**
	 * Evaluates the pawn horizontal connections: lateral pawns are of the same color
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawnHConnection(Board aBoard, int row, int col, Player aPlayer)
	{
		int value = 0;
		
		if (col > 0 && aBoard.getBoardTable()[row][col] == aBoard.getBoardTable()[row][col - 1])
			value += HCONNECTION_VALUE;
		if (col < 7 && aBoard.getBoardTable()[row][col] == aBoard.getBoardTable()[row][col + 1])
			value += HCONNECTION_VALUE;
		
		return value;
	}
	
	/**
	 * Evaluates the vertical connections: the pawn in front is of the same color
	 * @param aBoard
	 * @param row
	 * @param col
	 * @param aPlayer
	 * @return
	 */
	public static int evaluatePawnVConnection(Board aBoard, int row, int col, Player aPlayer)
	{
		int value = 0;
		
		if (aPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			if (row < 7 && aBoard.getBoardTable()[row][col] == aBoard.getBoardTable()[row + 1][col])
				value += VCONNECTION_VALUE;
		}
		else if (aPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			if (row > 0 && aBoard.getBoardTable()[row][col] == aBoard.getBoardTable()[row - 1][col])
				value += VCONNECTION_VALUE;
		}
		
		return value;
	}
	
	public static int assignValue(int value, int currentColor, int playingColor)
	{
		if (currentColor == playingColor)
			return value;
		else
			return -value;
	}
	
	/**
	 * The following example is in favor of Blue 'b'.
	 * x means anyone could occupy the square
	 * . means empty square
	 * 3 b b x
	 * 2 x . .
	 * 1 x . x
	 *   A B C
	 * @param aBoard
	 * @param maxPlayer
	 * @return
	 */
	public static boolean isWinningPosition_1(Board aBoard, Player maxPlayer)
	{
		if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			if (aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][0] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][1] == Board.NULL_PAWN &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][2] == Board.NULL_PAWN &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW + 1][1] == Board.NULL_PAWN)
				return true;
		}
		else if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			if (aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][0] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][1] == Board.NULL_PAWN &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][2] == Board.NULL_PAWN &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW - 1][1] == Board.NULL_PAWN)
				return true;
		}
		return false;
	}
	
	/**
	 * The following example is in favor of Blue 'b'.
	 * x means anyone could occupy the square
	 * . means empty square
	 * 3 x b x
	 * 2 b . x
	 * 1 x x x
	 *   A B C
	 * @param aBoard
	 * @param maxPlayer
	 * @return
	 */
	public static boolean isWinningPosition_2(Board aBoard, Player maxPlayer)
	{
		if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			// Left side
			if (aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][0] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][1] == Board.NULL_PAWN)
				return true;
			
			// Right side
			if (aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][6] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][7] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][6] == Board.NULL_PAWN)
				return true;
		}
		else if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			// Left side
			if (aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][0] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][1] == Board.NULL_PAWN)
				return true;
			
			// Right side
			if (aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][6] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][7] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][6] == Board.NULL_PAWN)
				return true;
		}
		return false;
	}
	
	/**
	 * The following example is in favor of Blue 'b'.
	 * x means anyone could occupy the square
	 * . means empty square
	 * 3 b x x
	 * 2 x b x
	 * 1 x x w
	 *   A B C
	 * @param aBoard
	 * @param maxPlayer
	 * @return
	 */
	public static boolean isWinningPosition_3(Board aBoard, Player maxPlayer)
	{
		if (maxPlayer.getPlayerValue() == Player.WHITE_PLAYER)
		{
			// Left side
			if ((aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][0] == maxPlayer.getPawnType() || aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][2] == maxPlayer.getPawnType()) &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW + 1][0] == Board.NULL_PAWN ||
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW + 1][2] == Board.NULL_PAWN)
				return true;
			
			// Right side
			if ((aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][7] == maxPlayer.getPawnType() || aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW - 1][5] == maxPlayer.getPawnType()) &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW][6] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW + 1][7] == Board.NULL_PAWN ||
					aBoard.getBoardTable()[Player.BLUE_HOME_LEVEL_ROW + 1][5] == Board.NULL_PAWN)
				return true;
		}
		else if (maxPlayer.getPlayerValue() == Player.BLUE_PLAYER)
		{
			// Left side
			if ((aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][0] == maxPlayer.getPawnType() || aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][2] == maxPlayer.getPawnType()) &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][1] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW - 1][0] == Board.NULL_PAWN ||
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW - 1][2] == Board.NULL_PAWN)
				return true;
			
			// Right side
			if ((aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][7] == maxPlayer.getPawnType() || aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW + 1][5] == maxPlayer.getPawnType()) &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW][6] == maxPlayer.getPawnType() &&
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW - 1][7] == Board.NULL_PAWN ||
					aBoard.getBoardTable()[Player.WHITE_HOME_LEVEL_ROW - 1][5] == Board.NULL_PAWN)
				return true;
		}
		return false;
	}
}
